package service

import (
	"Gin/app/dao"
	"Gin/app/model"
	"Gin/app/vo"
	"Gin/config"
	"Gin/middle/jwt"
	"Gin/utils/Redis"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"github.com/go-redis/redis/v8"
	"strconv"
	"time"
)

type UserService struct {
}

var userDao *dao.UserDao

func (us *UserService) Login(from *vo.LoginVo) *vo.UserVo {
	usr := userDao.FindByUserName(from.UserName)
	uPass := getMd5Pass(from.Password)
	uPass = getMd5Pass(uPass)
	if usr == nil || uPass != usr.PassWord {
		return nil
	}
	token, _ := jwt.GenerateToken(usr.Id, usr.CreateTime, usr.UserName)
	client := Redis.GetClient()
	client.Set(client.Context(), Redis.UserKey+token, usr, Redis.KeyExpireTime)
	userVo := &vo.UserVo{
		Id:       usr.Id,
		TickName: usr.TickName,
		Image:    usr.Image,
		Token:    token,
	}
	return userVo
}

func (us *UserService) Register(form *vo.RegisterVo, ip string) (*model.User, error) {
	if ip == "::1" {
		ip = "127.0.0.1"
	}
	if userDao.IsExistUser(form.UserName) {
		return nil, config.UserNameExistError
	}
	md5Pass := getMd5Pass(form.Password)
	usr := &model.User{
		UserName:   form.UserName,
		TickName:   "chat2.0_yUbJq" + time.Now().Format("YYYY-MM-DD hh:mm:ss"),
		PassWord:   getMd5Pass(md5Pass),
		Times:      1,
		Image:      "https://bpic.588ku.com/element_origin_min_pic/19/04/09/e3330d623cad123abc8545573a86cc38.jpg",
		Ip:         ip,
		CreateTime: time.Now().Format("2006-01-02 15:04:05"),
		UpdateTime: time.Now().Format("2006-01-02 15:04:05"),
	}
	row, err := userDao.AddUser(usr)
	if err != nil || row == 0 {
		return nil, config.AddUserError
	}
	return usr, nil
}

// SearchFriend 搜索好友功能
func (us *UserService) SearchFriend(username string) (*vo.UserVo, error) {
	user := userDao.FindWithNike(username)
	if user == nil {
		return nil, config.NoFindTheUser
	}
	return user, nil
}

// GetChatList 获得历史聊天列表
func (us *UserService) GetChatList(fId int) []*model.ChatMessage {
	cli := Redis.GetClient()
	unread := getNuReadTotal(fId, cli)
	chatListMessage := make([]*model.ChatMessage, 5, 10)
	unreadTotal := make(map[int]int)
	total := 0
	if unread != nil {
		// 拉取离线消息
		for ind, val := range unread {
			key, _ := strconv.Atoi(ind)
			value, _ := strconv.Atoi(val)
			unreadTotal[key] = value
			getTheNewMessage(fId, key, cli)
		}
	}
	// 拉取用户的聊天列表
	last := cli.HGetAll(cli.Context(), fmt.Sprintf(Redis.UserLastMessage, fId)).Val()
	for index, value := range last {
		key, _ := strconv.Atoi(index)
		msg := &model.ChatMessage{}
		_ = json.Unmarshal([]byte(value), msg)
		if unreadTotal[key] != 0 {
			msg.Unread = unreadTotal[key]
		}
		// 查询数据库获取对应的信息
		tick, icon := userDao.GetUserInfo(key)
		from, _ := strconv.Atoi(index)
		msg.Id = from
		msg.Tick = tick
		msg.Icon = icon
		chatListMessage[total] = msg
		total++
	}
	return chatListMessage[:total]
}

// 获得用户未读消息条数
func getNuReadTotal(fId int, cli *redis.Client) map[string]string {
	exist := cli.Exists(cli.Context(), fmt.Sprintf(Redis.UserUnReadMessage, fId)).Val()
	if exist == 0 {
		return nil
	}
	unread := cli.HGetAll(cli.Context(), fmt.Sprintf(Redis.UserUnReadMessage, fId)).Val()
	//cli.Del(cli.Context(), fmt.Sprintf(Redis.UserUnReadMessage, fId))
	return unread
}

// 拉取离线消息
func getTheNewMessage(fromId, chatId int, cli *redis.Client) {
	OutLineMessageList := cli.LRange(cli.Context(), fmt.Sprintf(Redis.UserMQList, fromId, chatId), 0, -1)
	cli.Del(cli.Context(), fmt.Sprintf(Redis.UserMQList, fromId, chatId))
	cli.RPush(cli.Context(), fmt.Sprintf(Redis.UserMessageList, fromId, chatId), OutLineMessageList.Val())
}

// GetTheHistoryMessage 获取用户的历史聊天数据
func (us *UserService) GetTheHistoryMessage(from, target int) []*model.SendMessage {
	cli := Redis.GetClient()
	val := cli.LRange(cli.Context(), fmt.Sprintf(Redis.UserMessageList, from, target), 0, -1).Val()
	var historyList []*model.SendMessage
	for _, value := range val {
		chat := &model.SendMessage{}
		_ = json.Unmarshal([]byte(value), chat)
		historyList = append(historyList, chat)
	}
	return historyList
}

// SendAddFriendMessage 发送添加消息
func (us *UserService) SendAddFriendMessage(fMsg *vo.AddFriendMessage) {
	cli := Redis.GetClient()
	cli.HSet(cli.Context(), fmt.Sprintf(Redis.UserAddFriendMessage, fMsg.Target), strconv.Itoa(fMsg.From), fMsg)
}

// AddFriend 添加
func (us *UserService) AddFriend(userId, friendId int) bool {
	row, err := userDao.AddFriend(userId, friendId)
	if err != nil || row == 0 {
		return false
	}
	cli := Redis.GetClient()
	cli.HDel(cli.Context(), fmt.Sprintf(Redis.UserAddFriendMessage, userId), strconv.Itoa(friendId))
	return true
}

// UnAdd 不添加
func (us *UserService) UnAdd(userId, friendId int) {
	cli := Redis.GetClient()
	cli.HDel(cli.Context(), fmt.Sprintf(Redis.UserAddFriendMessage, userId), strconv.Itoa(friendId))
}

// GetAddFriendMessage 获取添加列表
func (us *UserService) GetAddFriendMessage(userId int) ([]*vo.AddFriendMessage, int) {
	cli := Redis.GetClient()
	addMessage := cli.HGetAll(cli.Context(), fmt.Sprintf(Redis.UserAddFriendMessage, userId)).Val()
	var friend []*vo.AddFriendMessage
	for _, value := range addMessage {
		f := &vo.AddFriendMessage{}
		_ = json.Unmarshal([]byte(value), f)
		friend = append(friend, f)
	}
	return friend, len(friend)
}

// GetFriendList 获取好友列表
func (us *UserService) GetFriendList(userId int) ([]*vo.UserVo, error) {
	list, err := userDao.GetFriendList(userId)
	if err == config.GetFriendListError {
		return nil, err
	}
	return list, nil
}

// AcknowledgeMessage 确认收到消息
func (us *UserService) AcknowledgeMessage(from, target int) {
	cli := Redis.GetClient()
	cli.HDel(cli.Context(), fmt.Sprintf(Redis.UserUnReadMessage, from), strconv.Itoa(target))
}

func getMd5Pass(password string) string {
	usPass := config.Salt1 + config.Salt2 + password + config.Salt3 + config.Salt4
	newPass := md5.Sum([]byte(usPass))
	md5Pass := fmt.Sprintf("%x", newPass)
	return md5Pass
}
